package net.cyndeline.GUI.actors

import akka.actor.Actor
import javafx.util.Duration
import javafx.animation.{Timeline, KeyFrame, Animation, TimelineBuilder}
import javafx.event.{ActionEvent, EventHandler}
import net.cyndeline.GUI.actors.messages.RenderMap
import net.cyndeline.GUI.rendering.JobScheduler

/**
 * Runs the rendering fps loop that draws images onto the screen by scheduling jobs indefinitely and sending them
 * to objects that draws them. 60 frame renderings will be scheduled per second.
 */
class RenderManager extends Actor {
  private val framesPerSecond = 60
  private val duration = Duration.millis(1000/framesPerSecond)
  private var currentRenderLoop: Option[Timeline] = None

  def receive = {
    case RenderMap(manager, subscribers, graphics, map, cameraEntity, pixelWidth, pixelHeight) => {
      val jobSchedule = new JobScheduler(manager, graphics, map, cameraEntity, pixelWidth, pixelHeight)

      /* A single frame that is looped. */
      val frame = new KeyFrame(duration,
        new EventHandler[ActionEvent]() {

          /* Everything that should happen in each frame. */
          def handle(event: ActionEvent) {
            val renderJob = jobSchedule.schedule
            val subs = subscribers.iterator
            while (subs.hasNext) {
              val s = subs.next()
              s.render(renderJob)
            }
          }
        })

      /* Only runs one loop at the time. */
      if (currentRenderLoop.isDefined) {
        currentRenderLoop.get.stop()
      }

      currentRenderLoop = Option(TimelineBuilder.create()
        .cycleCount(Animation.INDEFINITE)
        .keyFrames(frame)
        .build())

      currentRenderLoop.get.play()
    }

    case _ => throw new Error("Unknown message")
  }
}
